home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 275_01 / lcau31.c < prev   
Encoding:
C/C++ Source or Header  |  1980-01-01  |  23.8 KB  |  833 lines

  1.  
  2. /* lcau31.c                */
  3. /* (3,1) Linear Cellular Automaton    */
  4.  
  5. /* Reference:                */
  6. /*                    */
  7. /*    Kenneth E. Perry            */
  8. /*    Abstract Mathematical Art        */
  9. /*    BYTE                */
  10. /*    December, 1986            */
  11. /*    pages 181-192            */
  12.  
  13. /*    Copyright (C) 1987        */
  14. /*    Copyright (C) 1988        */
  15. /*    Harold V. McIntosh        */
  16. /*    Gerardo Cisneros S.        */
  17.  
  18. /* G. Cisneros, 4.3.87                        */
  19. /* 10 April 1987 - modified for (4,2) [HVM]            */
  20. /* 26 April 1987 - Multiple menus [HVM]                */
  21. /* 28 April 1987 - back modified to (4,1) [HVM]            */
  22. /* 28 April 1987 - version for XVI Feria de Puebla [HVM]    */
  23. /* 14 May 1987 - modified for (3,1) and general rule [HVM]    */
  24. /* 19 May 1987 - modified for (2,2) [HVM]            */
  25. /* 20 May 1987 - modified for (2,3) [HVM]            */
  26. /* 8 June 1987 - general rule for (4,1) [HVM]             */
  27. /* 12 June 1987 - cartesian product of (2,1) rules [HVM]    */
  28. /* 12 June 1987 - (2,1) rule with memory  [HVM]            */
  29. /* 14 June 1987 - individual cycles of evolution [HVM]        */
  30. /* 17 June 1987 - p-adic representation in plane [HVM]        */
  31. /* 22 June 1987 - 2 speed gliders via 16 transitions [HVM]    */
  32. /* 26 June 1987 - push, pop the rule [HVM]            */
  33. /* 26 June 1987 - conserve position of rule cursor [HVM]    */
  34. /* 27 June 1987 - incremental rule construction [HVM]        */
  35. /* 29 June 1987 - conserve position of cell pointer [HVM]    */
  36. /* 30 June 1987 - mark & unmark transitions, xchg x&X [HVM]    */
  37. /* 25 July 1987 - display and edit de Bruijn diagrams [HVM]    */
  38. /* 27 July 1987 - graph of transition probabilities [HVM]    */
  39. /* 4 September 1987 - PROB41.C for option 't' [HVM]        */
  40. /* 21 October 1987 - program disks disappeared            */
  41. /* 24 December 1987 - program reconstructed from listings    */
  42. /* 20 February 1988 - RIJN31.C for option 'd' [HVM]        */
  43. /* 10 April 1988 - include rule engineering from LCA41 [HVM]    */
  44.  
  45. # include <bdos.h>
  46.  
  47. # define COLGRAF     4  /* graph resolution            */
  48. # define T80X25      3  /* text resolution            */
  49. # define WHCYMAG     1  /* color quad for normal screen        */
  50. # define YELREGR     2  /* color quad for alternative screen    */
  51. # define TRR        16  /* row showing totalistic rule number    */
  52. # define TRC        56  /* column for totalistic rule number    */
  53. # define XRR        12  /* row displaying totalistic rule    */
  54. # define XRC        56  /* column for totalistic rule        */
  55. # define AL        320  /* array length (screen width)        */
  56. # define SL        40    /* short array length            */
  57. # define TS         7    /* distinct sums w/totalistic rule    */
  58. # define DS        27  /* (number of distinct neighborhoods)    */
  59. # define KK         3  /* number of states per cell        */
  60. # define NX         19    /* number of sample rules        */
  61. # define BD        11  /* maximum degree of b.p.        */
  62.  
  63. char xrule[NX][KK][KK][KK];
  64.  
  65. char ixrule[NX][DS]=
  66.  
  67.     "000111011022211211212212121",    /* nice cross hatching */
  68.     "000111011022211211010101011",    /* very complex glider */
  69.     "001011121112111102122010110",    /* v. bars w/entanglement */
  70.     "001212111222012021211012110",    /* cycles on dgl bgrnd    */
  71.     "002010000121000021210121012",    /* crosshatching */
  72.     "002010110011102200201210000",    /* bin ctr */
  73.     "001212111222012021211012110",    /* cycles on dgl bgrnd    */
  74.     "010000022020011001000000012",    /* shuttle squeeze */
  75.     "010002001022011100022000102",    /* coo gldrs */
  76.     "012101100200011111020112002",    /* crocodile skin */
  77.     "012101211210021101110111010",    /* mixture of types */
  78.     "012101210121012101210221111",    /* y/o on b/g */
  79.     "020100121221001000010020101",    /* slow glider - copies bar */
  80.     "020101102122002001220120212",    /* slow glider */
  81.     "020102221122012100201010221",    /* slow & fast gliders */
  82.     "021201121221011200101210111",
  83.     "010010101111011120221112000",    /* diagonal growth on mesh */
  84.     "101010202020202010101111111",    /* skewed triangle */
  85.     "212112112111211112121211112"    /* gliderettes & latice */
  86.  
  87.     ;
  88.  
  89. char   tabl[20][SL];                    /* workspace to construct table */
  90. char   ascrule[KK][KK][KK];                /* ASCII transition values */
  91. char   auxrule[KK][KK][KK];                /* auxiliary transition table */
  92. char   rulstk[10][KK][KK][KK];                /* pushdown for rules */
  93. char   prule1[8], prule2[8];                /* product rule specification */
  94. char   trule[TS]="0130232";
  95. int    binrule[KK][KK][KK];
  96. int    arr1[AL], arr2[AL];                /* line of cells */
  97. int    ru, ru0, ru1, ru2;                /* rule cursor */
  98. int    li, lj;                        /* cell pointer */
  99. int    rulptr;                        /* rule pd ptr */
  100. int    ix0, iy0;                    /* origin for pen moves */
  101. double wmul[KK], wmvl[KK];                /* left mass point */
  102. double wmur[KK], wmvr[KK];                /* right mass point */
  103. double bp[KK][KK][KK][KK];                /* bernstein polynomial */
  104.  
  105. main() {
  106. int  i, j, i0, i1, i2;
  107. int  more = 'r';
  108. char a, b, c;
  109.  
  110. ru=6; ru0=0; ru1=0; ru2=0;
  111. li=SL/2; lj=0;
  112. rulptr=0;
  113.  
  114. for (i=0; i<NX; i++) {                    /* copy to 3-index array */
  115. i0=0; i1=0; i2=0;
  116. for (j=0; j<DS; j++) {
  117.   xrule[i][i0][i1][i2]=ixrule[i][j];
  118.   i2++;
  119.   if (i2==KK) {i2=0; i1++;};
  120.   if (i1==KK) {i1=0; i0++;};
  121.   if (i0==KK) {i0=0; };
  122. };};
  123.  
  124.     videopalette(WHCYMAG);                /* white/cyan/magenta */
  125.  
  126.     tuto();
  127.     while (!kbdst()) rand();                /* wait for keypress */
  128.     kbdin();                        /* ignore it */
  129.     videomode(T80X25);
  130.     videoscroll(3,0,5,71,0,3);                /* menu on blue background */
  131.     videoscroll(19,0,24,71,0,3);
  132.     xtoasc(rand()%NX);
  133.     ranlin();                        /* random initial array */
  134.     auxblnk();                        /* uncomitted transitions */
  135.  
  136.     while (more!='n') {                    /* execute multiple runs */
  137.     rmenu();
  138.     lmenu();
  139.     while (0<1) {                    /* set up one run */
  140.     c=kbdin();
  141.     if (c=='g') break;                    /* go draw graph */
  142.     if (c=='q') more='n';                /* quit for good */
  143.     if (more=='n') break;
  144.     switch (c) {
  145.     case '@':                    /* numbered tot rule */
  146.         nutoto(numin(0));
  147.         totoasc();
  148.         rmenu();
  149.         videocursor(0,4,0);
  150.         break;
  151.     case '$':                    /* dozen totalistics */
  152.         j=numin(0);
  153.         for (i=0; i<12; i++) {
  154.           nutoto(j+i);
  155.           totoasc();
  156.           ranlin();
  157.           evolve();
  158.           };
  159.         videomode(T80X25);
  160.         rmenu();
  161.         lmenu();
  162.         break;
  163.     case '.':                    /* one cycle of evolution */
  164.         asctobin();
  165.         onegen(AL);
  166.         clmenu();
  167.         break;
  168.     case ',':                    /* one cycle of evolution */
  169.         videomode(COLGRAF);
  170.         pgrid();
  171.         for (i=0; i<200; i++) {pprob(); onegen(AL);};
  172.         videodot(190,195,3);
  173.         kbdin();
  174.         videomode(T80X25);
  175.         rmenu();
  176.         lmenu();
  177.         break;
  178.     case 'T':                    /* totalistic rule */
  179.         xblnk();
  180.         tmenu();
  181.         edtrule();
  182.         totoasc();
  183.         for (i0=0; i0<KK; i0++) {
  184.         for (i1=0; i1<KK; i1++) {
  185.         for (i2=0; i2<KK; i2++) {
  186.         ascrule[i0][i1][i2]=trule[i0+i1+i2];
  187.         };};};
  188.         videocursor(0,4,0);
  189.         rmenu();
  190.         xmenu(totonu(0));
  191.         break;
  192.     case 't':                    /* edit tri prob plots */
  193.         edtri();
  194.         rmenu();
  195.         lmenu();
  196.         break;
  197.         case 'r':                    /* edit rule */    
  198.         xblnk();
  199.         edrule();
  200.         videocursor(0,4,0);
  201.         rmenu();
  202.         break;
  203.         case 'l':                    /* edit cell string */
  204.         xblnk();
  205.         edline(8,40);
  206.         videocursor(0,3,0);
  207.         lmenu();
  208.         break;
  209.         case '#':                    /* read stored rule */
  210.         xmenu(NX);
  211.         xtoasc(lim(1,numin(0),NX)-1);
  212.         rmenu();
  213.             break;
  214.     case 'D':                    /* run through samples */
  215.         for (i=0; i<NX; i++) {
  216.           xmenu(i);
  217.           xtoasc(i);
  218.           ranlin();
  219.           evolve();
  220.           };
  221.         videomode(T80X25);
  222.         rmenu();
  223.         break;
  224.     case 'd':                    /* de Bruijn diagram */
  225.         edijn();
  226.         rmenu();
  227.         lmenu();
  228.         break;
  229.         case 'u':                    /* sparse init arry */
  230.         xblnk();
  231.         for (i=0; i<AL; i++) arr1[i]=0;
  232.         arr1[AL/4]=1;
  233.             arr1[AL/2]=1;
  234.             arr1[(3*AL)/4]=1;
  235.             arr1[(3*AL)/4+2]=1;
  236.         lmenu();
  237.             break;
  238.     case 'X':                    /* random rule */
  239.         xblnk();
  240.         i=rand();
  241.         for (i0=0; i0<KK; i0++) {
  242.         for (i1=0; i1<KK; i1++) {
  243.         for (i2=0; i2<KK; i2++) {
  244.           if (i == 0) i=rand();
  245.           ascrule[i0][i1][i2]='0'+i%KK;
  246.           i/=KK;
  247.         };};};
  248.         rmenu();
  249.         break;
  250.     case 'x':                    /* random rule */
  251.         xblnk();
  252.         for (i0=0; i0<KK; i0++) {
  253.         for (i1=0; i1<KK; i1++) {
  254.         for (i2=0; i2<KK; i2++) {
  255.           if (i == 0) i=rand();
  256.           if (auxrule[i0][i1][i2]==' ') {
  257.         ascrule[i0][i1][i2]='0'+i%KK;
  258.         i/=KK;
  259.         };
  260.           };};};
  261.         rmenu();
  262.         break;
  263.     case 'y':                    /* random line */
  264.         xblnk();
  265.         ranlin();
  266.             lmenu();
  267.         break;
  268.     case 'z':
  269.         for (i=0; i<AL; i++) arr1[i]=0;
  270.         lmenu();
  271.         break;
  272.     case 'Y':                    /* symmetrize rule */
  273.         for (i0=0; i0<KK; i0++) {
  274.         for (i1=0; i1<KK; i1++) {
  275.         for (i2=0; i2<KK; i2++) {
  276.         ascrule[i2][i1][i0]=ascrule[i0][i1][i2];      
  277.         };};};
  278.         rmenu();
  279.         break;
  280.     case 'B':                    /* begin barrier */
  281.         a=kbdin();
  282.         b=kbdin();
  283.         ascrule[0][a-'0'][b-'0']=a;
  284.         ascrule[1][a-'0'][b-'0']=a;
  285.         ascrule[2][a-'0'][b-'0']=a;
  286.         ascrule[3][a-'0'][b-'0']=a;
  287.         rmenu();
  288.         break;
  289.     case 'E':                    /* end barrier */
  290.         a=kbdin();
  291.         b=kbdin();
  292.         ascrule[a-'0'][b-'0'][0]=b;
  293.         ascrule[a-'0'][b-'0'][1]=b;
  294.         ascrule[a-'0'][b-'0'][2]=b;
  295.         ascrule[a-'0'][b-'0'][3]=b;
  296.         rmenu();
  297.         break;
  298.     case 'L':                    /* left glider link */
  299.         a=kbdin();
  300.         b=kbdin();
  301.         c=kbdin();
  302.         ascrule[a-'0'][b-'0'][c-'0']=c;
  303.         rmenu();
  304.         break;
  305.     case 'R':                    /* left glider link */
  306.         a=kbdin();
  307.         b=kbdin();
  308.         c=kbdin();
  309.         ascrule[a-'0'][b-'0'][c-'0']=a;
  310.         rmenu();
  311.         break;
  312.     case 'S':                    /* still life link */
  313.         a=kbdin();
  314.         b=kbdin();
  315.         c=kbdin();
  316.         ascrule[a-'0'][b-'0'][c-'0']=b;
  317.         rmenu();
  318.         break;
  319.     case 'U':                    /* push rule */
  320.         if (rulptr<10) rulptr++;
  321.         for (i0=0; i0<KK; i0++) {
  322.         for (i1=0; i1<KK; i1++) {
  323.         for (i2=0; i2<KK; i2++) {
  324.         rulstk[rulptr][i0][i1][i2]=ascrule[i0][i1][i2];
  325.         };};};
  326.         xmenu(rulptr);
  327.         break;
  328.     case 'V':                    /* pop rule */
  329.         for (i0=0; i0<KK; i0++) {
  330.         for (i1=0; i1<KK; i1++) {
  331.         for (i2=0; i2<KK; i2++) {
  332.         ascrule[i0][i1][i2]=rulstk[rulptr][i0][i1][i2];
  333.         };};};
  334.         if (rulptr>0) rulptr--;
  335.         rmenu();
  336.         break;
  337.     case 'G':                    /* fetch rule */
  338.         for (i0=0; i0<KK; i0++) {
  339.         for (i1=0; i1<KK; i1++) {
  340.         for (i2=0; i2<KK; i2++) {
  341.         ascrule[i0][i1][i2]=rulstk[rulptr][i0][i1][i2];
  342.         };};};
  343.         rmenu();
  344.         break;
  345.     case '=':
  346.         for (i=1; i<8;  i++) {
  347.         for (j=0; j<SL; j++) arr1[SL*i+j]=arr1[j];};
  348.         lmenu();
  349.         break;
  350.     case '~':
  351.         for (i=1; i<16;  i++) {
  352.         for (j=0; j<20; j++) arr1[20*i+j]=arr1[j];};
  353.         lmenu();
  354.         break;
  355.         default: break;
  356.         };
  357.     };
  358.     if (more=='n') break;
  359.     do {
  360.     evolve();
  361.     videocursor(0,0,0);
  362.     scrstr("?");
  363.     videocursor(0,0,34);
  364.     scrstr("y/n/cr");
  365.     more=kbdin();
  366.     } while (more=='\015');
  367.     videomode(T80X25);                    /* reset the screen */
  368.     if (more=='n') break;
  369.     };
  370.   videomode(T80X25);}    
  371.  
  372. /* edit the rule */
  373. edrule() {char c;
  374.   while (0<1) {
  375.     cscrrul();
  376.     videocursor(0,3,ru);
  377.     c=kbdin();
  378.     if (c=='\015') break;                /* carriage return exits */
  379.     switch (c) {
  380.     case '0': case '1': case '2':            /* state */
  381.       ascrule[ru0][ru1][ru2]=c;
  382.       videocattr(0,c,3,1);
  383.       rupl();
  384.       break;
  385.     case '\011':                    /* tab = next quad */
  386.       ru2=0; ru1=0; ru0++;
  387.       if (ru0==KK) ru0=0;
  388.       ru=KK*KK*ru0+6;
  389.       break;
  390.     case ' ': case '\315': rupl(); break;        /* space = advance */
  391.     case '\010': case '\313': rumi(); break;        /* backspace */
  392.     case '\013': case '\310': auxrule[ru0][ru1][ru2]='+'; break; /* up arrow */
  393.     case '\012': case '\320': auxrule[ru0][ru1][ru2]=' '; break; /* down arrow */
  394.     default: break;
  395.     };
  396.   };
  397. }
  398.  
  399. /* advance the rule cursor */
  400. rupl() {
  401.   ru2++;
  402.   if (ru2==KK) {ru2=0; ru1++;};
  403.   if (ru1==KK) {ru1=0; ru0++;};
  404.   if (ru0==KK) {ru0=0; };
  405.   ru=KK*(KK*ru0+ru1)+ru2+6;
  406.   }
  407.  
  408. /* retract the rule cursor */
  409. rumi() {
  410.   if (ru2!=0) ru2--; else {ru2=KK-1;
  411.   if (ru1!=0) ru1--; else {ru1=KK-1;
  412.   if (ru0!=0) ru0--; else {ru0=KK-1;
  413.      };};};
  414.   ru=KK*(KK*ru0+ru1)+ru2+6;
  415.   }
  416.  
  417. /* edit totalistic rule */
  418. edtrule() {char c; int  i;
  419.   i=0;
  420.   while (i<TS) {
  421.     c=trule[i];
  422.     videocursor(0,TRR,TRC+i);
  423.     videocattr(0,c,3,1);
  424.     c=kbdin();
  425.     if (c=='\015') break;
  426.     switch (c) {
  427.       case '0': case '1': case '2':             /* state */
  428.         trule[i]=c;
  429.         videocattr(0,c,2,1);
  430.         i++; break;
  431.       case ' ': case '\315':                /* space = advance */
  432.         i++; break;
  433.       case '\010': case '\313':                /* backspace */
  434.         if (i!=0) i--;
  435.         break;
  436.       default: break;
  437.       };
  438.     };
  439. }
  440.  
  441. /* edit the line of cells */
  442. edline(nr,nc) int nr, nc; {
  443. char c;
  444. int  i, j, k, l;
  445. int  aa, bb, cc;
  446. int  xx, yy, zz;
  447.  
  448.   videocursor(0,19,0);
  449.   scrstr("insert states with 0, 1, 2; move cursor");
  450.   videocursor(0,20,0);
  451.   scrstr("with keyboard arrows, space or backspace.");
  452.   videocursor(0,21,0);
  453.   scrstr("carriage return exits");
  454.   while (0<1) {
  455.   videocursor(0,lj+9,li);
  456.   c=kbdin();
  457.   if (c == '\015') {videoscroll(19,0,24,70,0,3); break;};
  458.   switch (c) {
  459.   case '0': case '1': case '2':     arr1[nc*lj+li]=c-'0'; break;    /* enter state */
  460.   case '\012': case '\320':        if (lj<nr-1) lj++; break;    /* down    */
  461.   case '\013': case '\310':        if (lj>0)    lj--; break;    /* up      */
  462.   case '\014': case '\315': case ' ':    if (li<nc-1) li++; break;    /* forward */
  463.   case '\010': case '\313':        if (li>0)    li--; break;    /* back    */
  464.   case '<': li=0;    break; /* left margin */
  465.   case '>': li=nc-1; break; /* right margin */
  466.   case 'z': for (k=0; k<nc; k++) arr1[nc*lj+k]=0; break;        /* clear row */
  467.   case 'Z': for (k=0; k<AL; k++) arr1[k]=0; lmenu(); break;
  468.   case '^': for (k=0; k<nc; k++) arr1[nc*lj+k]=arr1[nc*(lj-1)+k]; break;
  469.   case 'x': auxblnk(); break; /* uncomitted transitions */
  470.   case '=':                        /* insert transition */
  471.     if (lj==0) break;
  472.     yy=li+nc*(lj-1);
  473.     xx=li==0?yy+nc-1:yy-1;
  474.     zz=li==nc-1?yy-nc+1:yy+1;
  475.     c=arr1[yy+nc]+'0';
  476.     ascrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  477.     auxrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  478.     rmenu(); 
  479.     videocursor(0,lj+9,li);
  480.     videocattr(0,arr1[yy+nc],3,1);
  481.     cscrrul();
  482.     break;
  483.   case '*':                        /* insert transition */
  484.     if (lj==0) break;
  485.     for (i=0; i<nc; i++) {
  486.       yy=i+nc*(lj-1);
  487.       xx=i==0?yy+nc-1:yy-1;
  488.       zz=i==nc-1?yy-nc+1:yy+1;
  489.       c=arr1[yy+nc]+'0';
  490.       ascrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  491.       auxrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  492.       videocattr(0,arr1[yy+nc],3,1);
  493.       };
  494.     rmenu(); 
  495.     videocursor(0,lj+9,li);
  496.     cscrrul();
  497.     break;
  498.   case '.':                        /* point evolution */
  499.     if (lj==0) break;
  500.     yy=li+nc*(lj-1);
  501.     xx=li==0?yy+nc-1:yy-1;
  502.     zz=li==nc-1?yy-nc+1:yy+1;
  503.     arr1[yy+nc]=ascrule[arr1[xx]][arr1[yy]][arr1[zz]]-'0';
  504.     break;
  505.   case '?':                        /* evolution of panel */
  506.     if (lj==nr-1) {for (i=0; i<AL-nc; i++) arr1[i]=arr1[i+nc]; lj--; lmenu(); };
  507.     lj++;
  508.     for (i=0; i<nc; i++) {
  509.       yy=i+nc*(lj-1);
  510.       xx=i==0?yy+nc-1:yy-1;
  511.       zz=i==nc-1?yy-nc+1:yy+1;
  512.       arr1[yy+nc]=ascrule[arr1[xx]][arr1[yy]][arr1[zz]]-'0';
  513.       };
  514.     break;
  515.   case '/':                        /* conditional evolution */
  516.     if (lj==nr-1) {for (k=0; k<AL-nc; k++) arr1[k]=arr1[k+nc]; lj--; lmenu(); };
  517.     lj++;
  518.     for (i=0; i<nc; i++) {
  519.       j=0;
  520.       yy=i+nc*(lj-1);
  521.       xx=i==0?yy+nc-1:yy-1;
  522.       zz=i==nc-1?yy-nc+1:yy+1;
  523.       aa=arr1[xx]; if (aa>KK-1) j=KK;
  524.       bb=arr1[yy]; if (bb>KK-1) j=KK;
  525.       cc=arr1[zz]; if (cc>KK-1) j=KK;
  526.       if (auxrule[aa][bb][cc]==' ') j=KK;
  527.       if (j==0) j=ascrule[aa][bb][cc]-'0';
  528.       arr1[yy+nc]=j;
  529.       };
  530.     break;
  531.   default: break;
  532.       }; /* end switch */
  533.   for (k=0; k<nc; k++) {
  534.     videocursor(0,lj+9,k);
  535.     l=arr1[nc*lj+k]+'0';
  536.     videoputc(l=='0'?'.':l,1);
  537.     };
  538.   }; /* end while */
  539. } /* end edline */
  540.  
  541. /* display a screen of evolution */
  542. evolve() {int i, j;
  543.   videomode(COLGRAF);                    /* erase the screen */
  544.   videocursor(0,0,0);                    /* top text line */
  545.   scrstr(":");
  546.   scrrul();
  547.   asctobin();
  548.   for (j=8; j<200; j++) videodot(j,AL-1,2);
  549.   for (j=8; j<200; j++) {                /* evolve for 192 generations */
  550.     for (i=0; i<AL; i++) videodot(j,i,arr1[i]);
  551.     onegen(AL);
  552.     if (kbdst()) {kbdin(); break;};
  553.     };
  554. }
  555.  
  556. /* copy ascrule over to binrul */
  557. asctobin() {int i0, i1, i2;
  558.   for (i0=0; i0<KK; i0++) {
  559.   for (i1=0; i1<KK; i1++) {
  560.   for (i2=0; i2<KK; i2++) {
  561.     binrule[i0][i1][i2]=ascrule[i0][i1][i2]-'0';
  562.     };};};
  563. }
  564.  
  565. /* evolution for one generation */
  566. onegen(j) int j; {int i;
  567.   if (j<2) return;
  568.   arr2[0]=binrule[arr1[j-1]][arr1[0]][arr1[1]];
  569.   for (i=1; i<j-1; i++) arr2[i]=binrule[arr1[i-1]][arr1[i]][arr1[i+1]];
  570.   arr2[j-1]=binrule[arr1[j-2]][arr1[j-1]][arr1[0]];
  571.   for (i=0; i<j; i++) arr1[i]=arr2[i];
  572. }
  573.  
  574. /* map the automaton state into the unit square */
  575. pprob() {int i, j; float x, y, z, k;
  576. i=AL/2; k=(float)KK; z=(float)((197/(KK*KK))*KK*KK);
  577. x=0.0; for (j=1; j<30; j++) x=(x+(float)arr1[i+j])/k;
  578. y=0.0; for (j=1; j<30; j++) y=(y+(float)arr1[i-j])/k;
  579. x=(x+(float)arr1[i])/k;
  580. videodot((int)(z*(1.0-y)),(int)(z*x),1);
  581. }
  582.  
  583. /* set up a grid for the unit square */
  584. pgrid() {int i, j, k, l;
  585. k=KK*KK+1;
  586. l=195/(k-1);
  587. for (i=0; i<k; i++) {
  588. for (j=0; j<k; j++) {
  589. videodot(l*i,l*j,2);
  590. };};
  591. }
  592.  
  593. /* tutorial and Help screen */
  594. tuto() {
  595.     videomode(T80X25);
  596.     videocursor(0,2,0);
  597.     scrstr("<Copyright (C) 1987, 1988 - H.V.McIntosh, G.Cisneros S.>");
  598.     videocursor(0,4,0);
  599.     scrstr("             *** LIFE in One Dimension ***");
  600.     videocursor(0,6,0);
  601.     scrstr("Three States - Black(0), Cyan(1), Magenta(2).");
  602.     videocursor(0,8,0);
  603.     scrstr("First neighbors - one on each side, three altogether.");
  604.     videocursor(0,10,0);
  605.     scrstr("Complete transition rule - random, edited, or stored.");
  606.     videocursor(0,12,0);
  607.     scrstr("Totalistic transition rule - random, edited, or stored.");
  608.     videocursor(0,14,0);
  609.     scrstr("Initial Cellular Array - random, edited, or patterned.");
  610.     videocursor(0,16,0);
  611.     scrstr("Submenus in options t(probabilities) and d(de Bruijn)");
  612.     videocursor(0,17,0);
  613.     scrstr("will be displayed in response to typing ?");
  614.     videocursor(0,19,0);
  615.     scrstr("Use any key to terminate a display in progress.");
  616.     videocursor(0,22,0);
  617.     scrstr("now, ... press any key to continue.");
  618. }
  619.  
  620. /* rule menu */
  621. rmenu() {
  622.     videocursor(0,0,0);
  623.     scrstr("      000000000111111111222222222");
  624.     videocursor(0,1,0);
  625.     scrstr("      000111222000111222000111222");
  626.     videocursor(0,2,0);
  627.     scrstr("      012012012012012012012012012");
  628.     videocursor(0,3,0);
  629.     scrstr("Rule: ");
  630.     scrrul();
  631.     if (istot()==1) {videocursor(0,TRR,TRC); xmenu(totonu(0));};
  632.     videocursor(0,5,0);
  633.     scrstr("    r(rule), l(line), #nn(stored), g(graph), q(quit), t(prob),");
  634.     videocursor(0,6,0);
  635.     scrstr("           x(rand rule), y(rand line), u(unit line), d(deBruijn)");
  636.     videocursor(0,7,0);
  637.     scrstr("           @nn(tot/rule), $nn(12 tot/rules), T(ed tot/rule).");
  638.     videocursor(0,5,0);
  639.     }
  640.  
  641. /* totalistic rule menu*/
  642. tmenu() {
  643.     videocursor(0,TRR-2,TRC-6);
  644.     scrstr("      totalistic rule");
  645.     videocursor(0,TRR-1,TRC-6);
  646.     scrstr("      0..1..2");
  647.     videocursor(0,TRR,TRC-6);
  648.     scrstr("rule: ");
  649.     tscrrul();
  650.     videocursor(0,TRR,TRC);
  651.     }
  652.  
  653. /* plain line menu */
  654. lmenu() {int i, j; char c;
  655.   for (j=0; SL*j<AL; j++) {videocursor(0,9+j,0);
  656.   for (i=0; i<SL; i++) {c='0'+arr1[SL*j+i]; videoputc(c=='0'?'.':c,1); }; };
  657.   videocursor(0,5,0); }
  658.  
  659. /* color line menu */
  660. clmenu() {int c, i, j;
  661.   for (j=0; SL*j<AL; j++) {
  662.     for (i=0; i<SL; i++) {
  663.       videocursor(0,9+j,i);
  664.       c=arr1[SL*j+i];
  665.       videocattr(0,c==0?'.':'0'+c,color(c),1);
  666.       };};
  667.   videocursor(0,5,0); }
  668.  
  669. /* get compatible color */
  670. int color(i) int i; {
  671.   switch (i) {
  672.     case 0:  return 2;
  673.     case 1:  return 3;
  674.     case 2:  return 5;
  675.     case 3:  return 7;
  676.     default: return 6;
  677. };}
  678.  
  679. /* display rule number */
  680. xmenu(n) int n; {
  681. char xx[6]; int i, nn;  
  682.   nn=sprintf(xx,"%5u",n);
  683.   videocursor(0,XRR,XRC);
  684.   for (i=0; i<nn; i++) videoputc(xx[i],1);
  685.   videocursor(0,XRR,XRC); }
  686.  
  687. /* clear screen space for rule number */
  688. xblnk() {videocursor(0,XRR,XRC); scrstr("     "); videocursor(0,5,0); }
  689.  
  690. /* copy saved rule #n into active rule */
  691. xtoasc(n) int n; {int i0, i1, i2;
  692.     xmenu(n+1);
  693.     for (i0=0; i0<KK; i0++) {
  694.     for (i1=0; i1<KK; i1++) {
  695.     for (i2=0; i2<KK; i2++) {
  696.     ascrule[i0][i1][i2]=xrule[n][i0][i1][i2];
  697.     };};}; }
  698.  
  699. /* change totalistic rule to general rule */
  700. totoasc() {
  701. int i0, i1, i2;
  702. for (i0=0; i0<KK; i0++) {
  703. for (i1=0; i1<KK; i1++) {
  704. for (i2=0; i2<KK; i2++) {
  705. ascrule[i0][i1][i2]=trule[i0+i1+i2];
  706. };};};
  707. }
  708.  
  709. /* change decimal totalistic rule to sum values */
  710. nutoto(x) int x; {int i;
  711. for (i=0; i<TS; i++) {trule[i]=x%KK+'0'; x/=KK;};}
  712.  
  713. /* change sum values to decimal totalistic rule */
  714. int totonu(i) int i; {int r;
  715.   if (i<TS) r=(trule[i]-'0')+KK*totonu(i+1); else r=0;
  716.   return r; }
  717.  
  718. /* test whether a rule is totalistic */
  719. int istot() {int i0, i1, i2, l;
  720.     l=1;
  721.     trule[0]=ascrule[0][0][0];
  722.     trule[1]=ascrule[1][0][0];
  723.     trule[2]=ascrule[2][0][0];
  724.     trule[3]=ascrule[2][1][0];
  725.     trule[4]=ascrule[2][2][0];
  726.     trule[5]=ascrule[2][2][1];
  727.     trule[6]=ascrule[2][2][2];
  728.     for (i0=0; i0<KK; i0++) {
  729.     for (i1=0; i1<KK; i1++) {
  730.     for (i2=0; i2<KK; i2++) {
  731.     if (ascrule[i0][i1][i2]!=trule[i0+i1+i2]) l=0;
  732.     };};};
  733.     return l; }
  734.  
  735. /* generate a random line of cells in arr1 */
  736. ranlin() {int i, c;
  737. for (i=0; i<AL; i++) {
  738.   if (i%8 == 0) c=rand();
  739.   arr1[i]=c%KK; c/=KK;};
  740. }
  741.  
  742. /* clear auxrule to blanks */
  743. auxblnk() {int i0, i1, i2;
  744. for (i0=0; i0<KK; i0++) {
  745. for (i1=0; i1<KK; i1++) {
  746. for (i2=0; i2<KK; i2++) {
  747. auxrule[i0][i1][i2]=' ';
  748. };};};
  749. }
  750.  
  751. /* limit j to interval (i,k) */
  752. int lim(i,j,k) int i, j, k;
  753.     {if (i>=j) return i; if (k<=j) return k; return j;}
  754.  
  755. /* display the rule number on the screen */
  756. scrrul() {int i0, i1, i2;
  757.   for (i0=0; i0<KK; i0++) {
  758.   for (i1=0; i1<KK; i1++) {
  759.   for (i2=0; i2<KK; i2++) {
  760.   videoputc(ascrule[i0][i1][i2],1);
  761.   };};}; }
  762.  
  763. /* display the rule number on the screen in glorious technicolor */
  764. cscrrul() {int i, i0, i1, i2;
  765.   i=6;
  766.   for (i0=0; i0<KK; i0++) {
  767.   for (i1=0; i1<KK; i1++) {
  768.   for (i2=0; i2<KK; i2++) {
  769.   videocursor(0,3,i++);
  770.   videocattr(0,ascrule[i0][i1][i2],auxrule[i0][i1][i2]==' '?3:6,1);
  771.   };};}; }
  772.  
  773. /* display totalistic rule number by sum */
  774. tscrrul() {int i;
  775.   for (i=0; i<TS; i++) {videoputc(trule[i],1); }; }
  776.  
  777. /* change decimal totalistic rule to sum values */
  778. nutowo1(x) int x; {int i;
  779. for (i=0; i<TS; i++) {prule1[i]=x%2+'0'; x/=2;};}
  780.  
  781. /* change Wolfram rule number to decimal rule number */
  782. int wotonu1(i) int i; {int r;
  783.   if (i<TS) r=(prule1[i]-'0')+2*totonu(i+1); else r=0;
  784.   return r; }
  785.  
  786. /* change decimal number to Wolfram rule number */
  787. nutowo2(x) int x; {int i;
  788. for (i=0; i<TS; i++) {prule2[i]=x%2+'0'; x/=2;};}
  789.  
  790. /* change sum values to decimal totalistic rule */
  791. int wotonu2(i) int i; {int r;
  792.   if (i<TS) r=(prule2[i]-'0')+2*totonu(i+1); else r=0;
  793.   return r; }
  794.  
  795. /* turn ascrule into its Wolfram number and place on screen at (i,j) */
  796. woruno(i,j) int i, j; {
  797. char xx[10];
  798. int  k, l, i0, i1, i2;
  799.   k=0;
  800.   for (i0=KK-1; i0>=0; i0--) {
  801.   for (i1=KK-1; i1>=0; i1--) {
  802.   for (i2=KK-1; i2>=0; i2--) {
  803.     k=3*k+(ascrule[i0][i1][i2]-'0');
  804.     };};};
  805.   k=sprintf(xx,"%3d",k);
  806.   videocursor(0,i,j);
  807.   for (l=0; l<k; l++) videoputc(xx[l],1);
  808. }
  809.  
  810. /* write a string in graphics mode */
  811. scrstr(s) char *s;
  812.   {for (; *s != '\0'; s++) videoputc(*s,1); }
  813.  
  814. /* keyboard status */
  815. int kbdst() {return(bdos(11) & 0xFF);}
  816.  
  817. /* direct keyboard input, no echo */
  818. kbdin() {int c;
  819.   if ((c = bdos(7) & 0xFF) == '\0') c = (bdos(7) & 0xFF) | 0x80;
  820.   return(c);
  821. }
  822.  
  823. /* read number from keyboard */
  824. int numin(n) int n; {char c;
  825.   c=kbdin();
  826.   if (c>='0'&&c<='9') return(numin(10*n+(c-'0'))); else return(n);
  827. }
  828.  
  829. # include "PROB31.C"
  830. # include "RIJN31.C"
  831.  
  832. /* end */
  833.